package com.puzzlebazar.client.puzzle.model;

import java.io.Serializable;


public interface Move extends Serializable {
	
	/**
	 * A method so that moves can be visited
	 * 
	 * @param visitor The visitor visiting this move
	 * @throws Exception
	 */
	public void accept( MoveVisitor visitor ) throws Exception;
	
	/**
	 * Apply the move to the specified model.
	 * The user should call notifyObserver() on the move list
	 * after applying the move.
	 * 
	 * @param model The model to which to move should be applied
     * @return A Move (or MoveList) that can be used for a more efficient call to notifyObserver()
	 * @throws Exception
	 */
	public Move apply( PuzzleModel model ) throws Exception ;
	

	/**
	 * Unapply the move to the specified model
	 * The user should call notifyObserver() on the move list
	 * after applying the move.
	 * 
	 * @param model The model to which to move should be applied
     * @return A Move (or MoveList) that can be used for a more efficient call to notifyObserver()
	 * @throws Exception
	 */
	public Move unapply( PuzzleModel model ) throws Exception ;


	/**
	 * Access the time of this move
	 * 
	 * @return The time at which the move was entered, in milliseconds
	 */
	public long getTime();

	/**
	 * Sets the time of this move
	 * 
	 * @param time The time to set for this move, in milliseconds
	 */
	void setTime(long time);


	/**
	 * Return a simplified version of the current move (so the current object is not modified)
	 * If the object is a single move, it is returned diretly. If its a MoveList containing a single
	 * move, it will be converted to that move. If it is a MoveList containing multiple
	 * moves it is returned directly.
	 * 
	 * @return Simplified move (can be the original move)
	 */	
	public Move simplify();
}
